package models;

import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import play.data.validation.Email;
import play.data.validation.Required;
import play.db.jpa.Model;
import play.modules.search.Field;
import play.modules.search.Indexed;

@Indexed
@Entity
// @UniqueConstraint(columnNames = {"user_name","email"})
@Table(name = "Users")
public class User extends Model {

	@Field
	@Required
	@Column(name = "first_name")
	public String firstName;

	public boolean isDeactivated;

	@Field
	@Column(name = "middle_name")
	public String middleName;

	@Field
	@Required
	@Column(name = "last_name")
	public String lastName;

	@Field
	@Required
	@Column(name = "user_name")
	public String userName;

	@Required
	public String password;

	@Field
	@Required
	@Email
	public String email;

	public String phone;

	public String address;

	@Required
	public String city;

	@Required
	public String country;

	public String image;

	public boolean isNotified;

	public boolean hasRequestedDeletion;

	@OneToMany(mappedBy = "user", cascade = { CascadeType.REMOVE })
	public List<TaskUserUser> taskUserAssignee = new LinkedList<TaskUserUser>();

	@OneToMany(mappedBy = "assignee", cascade = { CascadeType.REMOVE })
	public List<TaskUserUser> taskAssigneeUser = new LinkedList<TaskUserUser>();

	@OneToMany(mappedBy = "user", cascade = { CascadeType.REMOVE })
	public List<ComponentUser> userComponents = new LinkedList<ComponentUser>();

	@OneToMany(mappedBy = "creator")
	public List<Task> createdTasks = new LinkedList<Task>();

	@OneToMany(mappedBy = "user")
	public List<EventUser> eventAttendees = new LinkedList<EventUser>();

	@OneToMany(mappedBy = "creator")
	public List<UserStory> userStories = new LinkedList<UserStory>();

	@OneToMany(mappedBy = "user", cascade = { CascadeType.REMOVE })
	public List<UserRoleProject> user_project_roles = new LinkedList<UserRoleProject>();

	@OneToMany(mappedBy = "reviewer", cascade = { CascadeType.REMOVE })
	public List<ComponentTaskTypeUser> taskTypeReviewers = new LinkedList<ComponentTaskTypeUser>();

	@OneToMany(mappedBy = "reviewer", cascade = { CascadeType.REMOVE })
	public List<TaskUser> taskReviewers = new LinkedList<TaskUser>();

	/**
	 * constructs a new user
	 * 
	 * @param firstName
	 * @param middleName
	 * @param lastName
	 * @param userName
	 * @param password
	 * @param email
	 * @param phone
	 * @param address
	 * @param city
	 * @param country
	 * @param image
	 */
	public User(String firstName, String middleName, String lastName,
			String userName, String password, String email, String phone,
			String address, String city, String country, String image) {
		super();
		this.firstName = firstName;
		this.middleName = middleName;
		this.lastName = lastName;
		this.userName = userName;
		this.password = password;
		this.email = email;
		this.phone = phone;
		this.address = address;
		this.city = city;
		this.country = country;
		this.image = image;
		this.isNotified = true;
	}

	/**
	 * Returns a list of the tasks assigned to a certain user withina specific
	 * project.
	 * 
	 * @param user
	 * @param project
	 * @return List<Task>
	 */
	public List<Task> getAssignedTasks(long projectId) {
		Project project = Project.findById(projectId);
		if (this != null && project != null) {
			List<Task> projectTasks = project.getAllProjectTasks();
			List<Task> userTasks = new LinkedList<Task>();
			if (projectTasks != null) {
				for (int i = 0; i < projectTasks.size(); i++) {
					if (projectTasks.get(i).getTaskAssignee() != null) {
						if (this.equals(projectTasks.get(i).getTaskAssignee())) {
							userTasks.add(projectTasks.get(i));
						}
					}
				}
			}
			return userTasks;
		}
		return null;
	}

	/**
	 * checks whether the user has a pending request to review a specific task.
	 * Returns true if he has and false otherwise
	 * 
	 * @author Rana Ashraf
	 * @param TaskId
	 * @return boolean
	 */
	public boolean hasRequestedReview(Long taskId) {
		Task task = Task.findById(taskId);
		TaskUser tu = TaskUser
				.find(
						"select tu from TaskUser tu where tu.reviewer=? and status=? and tu.task=?",
						this, false, task).first();
		if (tu == null)
			return false;
		else
			return true;
	}

	/**
	 * @param username
	 * @param password
	 * @return This method checks if the user enters a correct username and its
	 *         corresponding password
	 */
	public static User connect(String username, String password) {

		User user = find("byUserNameAndPassword", username, password).first();

		if (user == null)
			return null;
		if (user.isDeactivated)
			return null;

		return user;
	}

	/**
	 * returns a list of records in Task User User Table that match with the the
	 * given assignee
	 * 
	 * @param t
	 *            Task
	 * @param u
	 *            User
	 * @return
	 */
	public List<TaskUserUser> getUserTaskRelation() {

		List<TaskUserUser> TUU = TaskUserUser.find(
				"Select TUU from TaskUserUser TUU where TUU.assignee=? ", this)
				.fetch();
		return TUU;

	}

	public List<Task> getMySuggestedTasks() {
		List<Task> tasks = new LinkedList<Task>();

		List<TaskUserUser> TUU = this.getUserTaskRelation();

		for (int i = 0; i < TUU.size(); i++) {
			if (TUU.get(i).user != null)
				tasks.add(TUU.get(i).task);

		}
		return tasks;
	}
}
